Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(users): custom role at profile read #6875

Open
wants to merge 36 commits into
base: main
Choose a base branch
from

Conversation

Riddhiagrawal001
Copy link
Contributor

@Riddhiagrawal001 Riddhiagrawal001 commented Dec 18, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

This pr adds the functionality to read custom role profile read

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

  1. Create custom role at profile-level
    Request
curl --location 'http://localhost:9000/api/user/role' \
--header 'authorization: Bearer JWT' \
--data '{
    "role_scope": "merchant",
    "groups": [
        "operations_manage",
        "connectors_view"
    ],
    "role_name": "profile-level-custom-role",
    "entity_type":"profile"
}'

Response

{
    "error": {
        "type": "invalid_request",
        "message": "User Role Operation Not Supported",
        "code": "UR_23"
    }
}
  1. Older flows should work as before . Changes for create profile custom roles will be in consecutive pr
  2. Validate custom role
    If a role with the same name is created either below me or in my lineage , then i wouldn't be able to create the role with that same name
    Request
curl 'http://localhost:9000/api/user/role' \
  -H 'Accept: */*' \
  -H 'authorization: Bearer JWT' \
  --data-raw '{"role_scope":"merchant","groups":["operations_view","operations_manage"],"role_name":"m2-org"}'

Response

{
    "error": {
        "type": "invalid_request",
        "message": "Role name already exists",
        "code": "UR_35"
    }
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

Riddhiagrawal001 and others added 24 commits November 28, 2024 15:44
@Riddhiagrawal001 Riddhiagrawal001 requested review from a team as code owners December 18, 2024 07:41
@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Dec 18, 2024
@Riddhiagrawal001 Riddhiagrawal001 changed the title fix(users): custom role at profile read feat(users): custom role at profile read Dec 18, 2024
@Riddhiagrawal001 Riddhiagrawal001 self-assigned this Dec 18, 2024
@Riddhiagrawal001 Riddhiagrawal001 linked an issue Dec 18, 2024 that may be closed by this pull request
Comment on lines 100 to 105
} else if requestor_entity_from_role_scope < role_entity_type {
return Err(report!(UserErrors::InvalidRoleOperation)).attach_printable(format!(
"User is trying to create role of type {} and scope {}",
requestor_entity_from_role_scope, role_entity_type
));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be checked first.

Comment on lines 120 to 121
let profile_id =
matches!(role_entity_type, EntityType::Profile).then_some(user_from_token.profile_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this a match instead.

Comment on lines 90 to 105
if user_entity_type < role_entity_type {
return Err(report!(UserErrors::InvalidRoleOperation)).attach_printable(format!(
"{} is trying to create {} ",
user_entity_type, role_entity_type
));
} else if user_entity_type < requestor_entity_from_role_scope {
return Err(report!(UserErrors::InvalidRoleOperation)).attach_printable(format!(
"{} is trying to create role of scope {} ",
user_entity_type, requestor_entity_from_role_scope
));
} else if requestor_entity_from_role_scope < role_entity_type {
return Err(report!(UserErrors::InvalidRoleOperation)).attach_printable(format!(
"User is trying to create role of type {} and scope {}",
requestor_entity_from_role_scope, role_entity_type
));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate these ifs.

Comment on lines 247 to 249
"{} is trying to update {} ",
user_role_info.get_entity_type(),
role_info.get_entity_type()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print scope as well here.

let user_role_info = user_from_token.get_role_info_from_db(&state).await?;

let max_from_scope_and_entity = cmp::max(
user_role_info.get_entity_type(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be taken from role_info.

Comment on lines 268 to 273
.profile_id
.as_ref()
.map(|profile_id_from_role| {
profile_id_from_role == profile_id
&& role.scope == RoleScope::Profile
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use is_some_and.

Comment on lines 287 to 289
DieselError::NotFound => {
Err(report!(err)).change_context(errors::DatabaseError::NotFound)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this throw error if nothing is found?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case wont come as it will resolve in Ok when value is [] . Hence will remove this

Ok(roles_list)
roles_list.ok_or(
errors::StorageError::ValueNotFound(
"No role available with role_name={role_name} in org_id = {org_id:?}".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe printing the EntityTypePayload is more appropriate here.

Comment on lines 226 to 228
.eq(RoleScope::Organization)
.or(dsl::scope.eq(RoleScope::Merchant))
.or(dsl::scope.eq(RoleScope::Profile)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make scopes also a Vec? Will that improve readability?

Converting to Vec will give us an advantage, we don't have to change the query if scopes are added or removed. But I assume, we won't be changing scopes anytime soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the query with the discussed changes

Comment on lines 109 to 111
EntityType::Profile,
EntityType::Merchant,
EntityType::Organization,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These entity types should be based on the Payload's entity type.

If we run this query for profile level Payload, we will also search for org level entity_types which is wrong (correct me if I am wrong).

And if it is not based on the payload, then this query is technically a subset for the list query.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its been modified to check with list query

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
M-database-changes Metadata: This PR involves database schema changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(users): Add profile level custom role
2 participants